package aishua.com.mytestapplist.utils;


import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Base64;


@SuppressLint({ "DefaultLocale", "SimpleDateFormat" })
public class CommonMethods {
	
	public static byte[] IV = new byte[8];
	
	public static byte[] PATCH = new byte[]{(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20, 
		(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20};

	public static byte byteXOR(byte src, byte src1) {
		return (byte) ((src & 0xFF) ^ (src1 & 0xFF));
	}

	public static byte[] bytesXOR(byte[] src, byte[] src1) {
		
		int length = src.length;
		if (length != src1.length) {
			return null;
		}
		byte[] result = new byte[length];
		for (int i = 0; i < length; i++) {
			result[i] = byteXOR(src[i], src1[i]);
		}
		return result;
	}
	
	
    public static int bytes2Int(byte[] byteColor) {
    	
    	return byteArrayToInt(byteColor);	
    }
	
	public static short bytesToShort(byte[] outBuf){
		
		if (outBuf.length < 2) {
			return (short)(outBuf[0] < 0 ? outBuf[0] + 256 : outBuf[0]); 
		} else {
			return (short)(((outBuf[0] < 0 ? outBuf[0] + 256 : outBuf[0]) << 8) + (outBuf[1] < 0 ? outBuf[1] + 256 : outBuf[1]));
		}
		
	}
	
    public static String toHexString(byte[] d, int s, int n) {
        final char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        final char[] ret = new char[n * 2];
        final int e = s + n;

        int x = 0;
        for (int i = s; i < e; ++i) {
                final byte v = d[i];
                ret[x++] = hexArray[0x0F & (v >> 4)];
                ret[x++] = hexArray[0x0F & v];
        }
        return new String(ret);
}
	public static byte[] short2Bytes(short in){
		
        ByteBuffer bb = ByteBuffer.allocate(2);
        bb.putShort(in);
        return bb.array();
			
	}
	
	public static byte[] short2OctBytes(short in) {
		
		byte[] out = new byte[2];
		
		if (in < 0 || in >= 9999) {
			out[0] = 0;
			out[1] = 0;
			return out;
		}
		
		byte hight = (byte) ((in%100)/10);
		byte low = (byte) (in%10);
		out[1] = (byte) (hight*16 + low);
		
		hight = (byte) (in/1000);
		low = (byte) ((in/100)%10);
		out[0] = (byte) (hight*16 + low);
		return out;
	}
	
    public static int getColorInt(String hexColor) {
    	
    	byte[] byteColor = str2bytes(hexColor);
    	return byteArrayToInt(byteColor);	
    }
    
    
    public static int byteArrayToInt(byte[] b) {
    	
        int value= 0;
        for (int i = 0; i < b.length; i++) {
            int shift = (b.length - 1 - i) * 8;
            value +=(b[i] & 0x000000FF) << shift;
        }
        return value;
    }
	
	public static byte[] intToByteArray(int i) { 
	
		byte[] result = new byte[4];   
		result[0] = (byte)((i >> 24) & 0xFF);
		result[1] = (byte)((i >> 16) & 0xFF);
		result[2] = (byte)((i >> 8) & 0xFF);
		result[3] = (byte)(i & 0xFF);
		return result;
	}
	
	public static byte str2byte(String src) {
		byte[] result = str2bytes(src);
		return result[0];
	}
	
	public static String byte2HexString(byte data) {
		byte[] datas = new byte[]{data};
		return bytesToHexString(datas);
	}
	
    public static byte[] str2bytes(String src) {
    	
        if (src == null || src.length() == 0 || src.length() % 2 != 0) {
            return null;
        }
        int nSrcLen = src.length();
        byte byteArrayResult[] = new byte[nSrcLen / 2];
        StringBuffer strBufTemp = new StringBuffer(src);
        String strTemp;
        int i = 0;
        while (i<strBufTemp.length()-1)
        {
            strTemp = src.substring(i, i+2);
            byteArrayResult[i/2] = (byte) Integer.parseInt(strTemp, 16);
            i+=2;
        }
        return byteArrayResult;
    }
   
	public static String bytesToHexString(byte[] bytes) {
		
        if (bytes == null)
        {
            return "";
        }
        StringBuffer buff = new StringBuffer();
        int len = bytes.length;
        for (int j = 0; j < len; j++)
        {
            if ((bytes[j] & 0xff) < 16)
            {
                buff.append('0');
            }
            buff.append(Integer.toHexString(bytes[j] & 0xff));
        }
        return buff.toString().toUpperCase();
    }
	
    public static int toInt(byte[] b, int s, int n) {
        int ret = 0;

        final int e = s + n;
        for (int i = s; i < e; ++i) {
                ret <<= 8;
                ret |= b[i] & 0xFF;
        }
        return ret;
}
    
    public static boolean getSW(byte[] datas){
    	int n = datas.length;
    	return ((datas[n - 2] << 8) | (0xFF & datas[n - 1]))==(short)0x9000;
    }
 
	@SuppressLint("DefaultLocale")
	public static String desecb(String key, String data, int mode) {
		
        try {
        	int opmode = (mode == 0)? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
        	
        	SecretKey keySpec = null;
        	
        	Cipher enc = null;
        	
            if(key.length()==16){
	        	keySpec = new SecretKeySpec(str2bytes(key), "DES");//key
	            
	        	enc = Cipher.getInstance("DES/ECB/NoPadding");
            }
            else if(key.length()==32){
            	keySpec = new SecretKeySpec(str2bytes(key+key.substring(0, 16)), "DESede");
	            
	        	enc = Cipher.getInstance("DESede/ECB/NoPadding");
        	}
        	else if(key.length()==48){
	        	keySpec = new SecretKeySpec(str2bytes(key), "DESede");//key
	            
	        	enc = Cipher.getInstance("DESede/ECB/NoPadding");
        	}
        	else{
        		return null;
        	}
        	
        	enc.init(opmode, keySpec);
        	
        	return (bytesToHexString(enc.doFinal(str2bytes(data)))).toUpperCase();
        	
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
	}
	
	public static byte[] des3EncodeCBC(byte[] key, byte[] keyiv, byte[] data)
            throws Exception {

        Key deskey = null;
        DESedeKeySpec spec = new DESedeKeySpec(key);
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        deskey = keyfactory.generateSecret(spec);

        Cipher cipher = Cipher.getInstance("desede" + "/CBC/NoPadding");
        IvParameterSpec ips = new IvParameterSpec(keyiv);
        cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
        byte[] bOut = cipher.doFinal(data);

        return bOut;
    }
	
	public static String descbc(String key, String data, int mode) {

        try {
        	int opmode = (mode == 0)? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
        	
        	SecretKey keySpec = null;
        	
        	Cipher enc = null;
        	
            if(key.length()==16){
	        	keySpec = new SecretKeySpec(str2bytes(key), "DES");//key
	            
	        	enc = Cipher.getInstance("DES/CBC/NoPadding");
            }
            else if(key.length()==32){
            	keySpec = new SecretKeySpec(str2bytes(key+key.substring(0, 16)), "DESede");
	            
	        	enc = Cipher.getInstance("DESede/CBC/NoPadding");
        	}
        	else if(key.length()==48){
	        	keySpec = new SecretKeySpec(str2bytes(key), "DESede");//key
	            
	        	enc = Cipher.getInstance("DESede/CBC/NoPadding");
        	}
        	else{
        		return null;
        	}
        	
        	enc.init(opmode, keySpec);
        	
        	return (bytesToHexString(enc.doFinal(str2bytes(data)))).toUpperCase();
        	
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
	
	}
	
	public static String reverseStringBit(String src){
		
		byte[] bits = str2bytes(src);
		for (int i = 0; i < bits.length; i++) {
			bits[i] = (byte)(0xff-bits[i]);
		}
		return bytesToHexString(bits);
	}
	
	
	@SuppressLint("DefaultLocale")
	public static String getRandomString(int length) {
		
	    String base = "0123456789";
	    Random random = new Random();
	    StringBuffer sb = new StringBuffer();
	    for (int i = 0; i < length; i++) {   
	        int number = random.nextInt(base.length());   
	        sb.append(base.charAt(number));   
	    }   
	    return sb.toString().toUpperCase();   
	 } 
	
	/**
	 * ����MAC
	 * @param mode��1������ضϣ�else�ض�4�ֽ�
	 * @param key
	 * @param Input
	 * @return
	 */
	public static byte[] clacMac(int mode, byte[] key, byte[] Input) {
		
		int length = Input.length;
		int x = length % 8;
		int addLen = 0;
		if (x != 0) {
			addLen = 8 - length % 8;
		}
		int pos = 0;
		byte[] data = new byte[length+addLen+8];
		System.arraycopy(IV, 0, data, 0, IV.length);
		System.arraycopy(Input, 0, data, 8, length);
		System.arraycopy(PATCH, 0, data, 8+length, addLen);
		byte[] oper1 = new byte[8];
		System.arraycopy(data, pos, oper1, 0, 8);
		pos += 8;
		for (int i = 1; i < data.length / 8; i++) {
			byte[] oper2 = new byte[8];
			System.arraycopy(data, pos, oper2, 0, 8);
			byte[] t = bytesXOR(oper1, oper2);
			t = str2bytes(desecb(bytesToHexString(key), bytesToHexString(t),  0));
			oper1 = t;
			pos += 8;
		}
		if (mode == 1) {
			return oper1;
		}
		byte[] retBuf = new byte[4];
		System.arraycopy(oper1, 0, retBuf, 0, 4);
		return retBuf;
	}
	
	public static String getCurrentDate(String format) {
		
		SimpleDateFormat sdf =  new SimpleDateFormat(format);
		return sdf.format(new Date(System.currentTimeMillis()));
	}
	
	public static byte[] getAntBytes(byte[] src) {
		
	    int bytecount = src.length; 
	    byte[] data = new byte[bytecount];
	    byte temp;                                               
	    byte ant = (byte)0xff;
	    for (int i = 0; i < bytecount; i++){
	          temp = src[i];
	          data[i] = (byte) (temp ^ ant);                                
	    }
	    return data;
	}
	
	public static String Base64Decode(String code) {
		if(code==null){
			return "null";
		}
		byte[] encode = Base64.decode(code, Base64.DEFAULT);
		String result = new String(encode, Charset.forName("utf-8"));
		return result;
	}
	
	public static String Base64Encode(String code) {
		if (null == code) {
			return "";
		}
		byte[] encode = Base64.encode(code.getBytes(), Base64.DEFAULT);
		String result = new String(encode, Charset.forName("utf-8"));
//		result = result.replace("+", "%2B");
		return result;
	}
	
	public static String exchangeHighAndLow(String data) {
		if (data.length() %2 != 0) {
			return "";
		} else {
			String res = "";
			for(int i=0; i<data.length()/2; i++) {
				res += data.substring(2*i+1, 2*i+2);
				res += data.substring(2*i, 2*i+1);
			}
			return res;
		}
	}
	
	/**
	 * 
	 * @param strSrc
	 * @param encName MD5\SHA-1\SHA-256
	 * @return
	 */
	public static String Encrypt(String strSrc, String encName) {
		MessageDigest md = null;
		String strDes=null;
		try {
			byte[] bt= strSrc.getBytes("utf-8");
            if (encName==null||encName.equals("")) {
                encName="MD5";
            }
			md = MessageDigest.getInstance(encName);
			md.update(bt);
			strDes = bytesToHexString(md.digest());  //to HexString
		} catch (NoSuchAlgorithmException e) {
	        return strDes;
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return strDes;
	}
	
	public static String Encrypt(byte[] strSrc, String encName) {
		MessageDigest md = null;
		String strDes=null;
		try {
            if (encName==null||encName.equals("")) {
                encName="MD5";
            }
			md = MessageDigest.getInstance(encName);
			md.update(strSrc);
			strDes = bytesToHexString(md.digest());  //to HexString
		} catch (NoSuchAlgorithmException e) {
	        return strDes;
		}
		return strDes;
	}
	
	
	public static String getPackageSha1(Context context, String packageName){
		   try {
	           /** 通过包管理器获得指定包名包含签名的包信息 **/
			   PackageManager manager =  context.getPackageManager();
			   PackageInfo packageInfo = manager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
	           /******* 通过返回的包信息获得签名数组 *******/
			   Signature[] signatures = packageInfo.signatures;
	           /******* 循环遍历签名数组拼接应用签名 *******/
			   
			   byte[] sign_bytes = signatures[0].toByteArray();
			   return CommonMethods.Encrypt(sign_bytes, "sha-1");
	           /************** 得到应用签名 **************/
	       } catch (NameNotFoundException e) {
	           e.printStackTrace();
	       }
		   return null;
	}
}